package inge_soft.gestoriusNuevo.persistence.DAO.implementation;

import inge_soft.gestoriusNuevo.persistence.DAO.abstraction.IUsuarioDAO;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.Usuario;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Repository("usuarioDAO")
public class UsuarioDAO implements IUsuarioDAO {
	
	static final Logger logger = Logger.getLogger(UsuarioDAO.class);
	@PersistenceContext
	private EntityManager entityManager;

	// Metodo para devolver un objeto de la base de datos
	// La transaccion se marca para solo lectura. Por defecto soporta
	// la transaccion actual, si no existe la crea
	@Transactional(readOnly = true)
	public Usuario findById(long id) throws DataAccessException {
		if (!logger.isDebugEnabled()) {
			logger.info("Buscando en la tabla Usuario por ID: " + id);
		}
		return entityManager.find(Usuario.class, id);
	}

	// Metodo para persistir un objeto en la base de datos
	// Soporta la transaccion actual,
	// si no existe una abierta, lanza una excepcion
	@Transactional(propagation = Propagation.MANDATORY)
	public void save(Usuario usuario) throws DataAccessException {

		entityManager.persist(usuario);
		
		if (!logger.isDebugEnabled()) {
			logger.info("Persistido " + usuario.toString());
		}
	}

	// Metodo para actualizar un objeto en la base de datos
	// Soporta la transaccion actual,
	// si no existe una abierta, lanza una excepcion
	@Transactional(propagation = Propagation.MANDATORY)
	public void update(Usuario usuario) throws DataAccessException {
		entityManager.merge(usuario);
		if (!logger.isDebugEnabled()) {
			logger.info("Actualizado " + usuario.toString());
		}
	}

	// Metodo para eliminar un objeto en la base de datos
	// Soporta la transaccion actual,
	// si no existe una abierta, lanza una excepcion
	// COMENTADO PORQUE HAY QUE VER COMO SE REALIZA LA ELIMINACION.
	@Transactional(propagation = Propagation.MANDATORY)
	public void delete(Usuario usuario) throws DataAccessException {
		//Usuario r = findById(usuario.getId());
		//if (r != null) {
			entityManager.remove(usuario);
			if (!logger.isDebugEnabled()) {
				logger.info("Eliminado " + usuario.toString());
			}
		//}
	}

	// Metodo para devolver una lista de objetos de la base de datos
	// La transaccion se marca para solo lectura. Por defecto soporta
	// la transaccion actual, si no existe la crea
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	public List<Usuario> listAll() throws DataAccessException {
		if (!logger.isDebugEnabled()) {
			logger.info("Buscando en la tabla Usuario todos los registros");
		}
		Query q = entityManager.createQuery("SELECT u FROM Usuario u");
		return q.getResultList();
	}

	// Metodo para devolver una lista ordenada de objetos de la base de datos
	// La transaccion se marca para solo lectura. Por defecto soporta
	// la transaccion actual, si no existe la crea
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	public List<Usuario> listAllOrderByName() {
		if (!logger.isDebugEnabled()) {
			logger.info("Buscando en la tabla Usuario todos los registros ordenados");
		}
		Query q = entityManager
				.createQuery("SELECT u FROM Usuario u ORDER BY u.nombre ASC");
		return q.getResultList();
	}
	
	
}
